# -*- coding: utf-8 -*-
#分类模块
##################################
# import numpy as np
import cv2 as cv
from math import sqrt
import numpy as np

#通过RGB加权欧式距离进行匹配分类
RGB_WEIGHT_DIS=102;
HSV_COLOR_RANGE=104;

# 获取RGB加权欧式距离
#color1：使用的是BGR
def getRGBWDIS(color1,color2):
	r = color1[2] - color2[2];
	g = color1[1] - color2[1];
	b = color1[0] - color2[0];
	rmean = (color1[2] + color2[2])/2;
	return sqrt((2 + rmean/256)*(r**2) + 4 * (g**2) + (2+(255-rmean)/256)*(b**2));

def isBlack(color):
	minBlack=[0,0,0];
	maxBlack=[145,145,145];
	if minBlack[0] <= color[0] and color[0] <= maxBlack[0] and minBlack[1] <= color[1] and color[1] <= maxBlack[1] and minBlack[2] <= color[2] and color[2] <= maxBlack[2]:   
		return True;
	return False;

count=0;

#获取中心的正方形ROI
def getCenterSquareROI(img,size):
	copyImg=np.copy(img);
	#预设的检测框宽高
	cx,cy=copyImg.shape[1]//2,copyImg.shape[0]//2;
	#找出最短边
	minV=cx;
	if cy<cx:
		minV=cy;
	#计算size是否需要保留(如果size大于了minV那么就不保留)
	if size>minV:
		size=minV
	half=size//2;
	x1,y1,x2,y2=cx-half,cy-half,cx+half,cy+half;
	#提取ROI
	roi=copyImg[y1:y2,x1:x2];
	return roi;

#获取一张图片的BGR通道均值
def getBlockBGRAvg(block):
	global count;
	#提取中心的一个size*size大小的方形ROI区域
	#降低色块边缘干扰像素带来的影响
	block=getCenterSquareROI(block,32);
	#返回均值
	count+=1;
	cv.imwrite("C:\\Users\\ASUS\\Desktop\\img\\little\\"+str(count)+".jpg",block);
	return cv.mean(block);

#定义6种颜色的HSV范围
'''
red=[(0,43,46),(10,255,255),(156,43,46),(180,255,255)];
white=[(0,0,211),(180,30,255)];
orange=[(11,43,46),(25,255,255)];
yellow=[(26,43,46),(34,255,255)];
green=[(35,43,46),(77,255,255)];
blue=[(100,43,46),(124,255,255)];
'''

#定义的阈值，颜色对应参考上方
threshold=[[(0,43,46),(10,255,255),(130,43,46),(180,255,255)]
		,[(0,0,211),(180,70,255),(0,0,46),(180,70,255)]
		,[(11,43,46),(25,255,255)]
		,[(26,43,46),(43,255,255)]
		,[(44,43,46),(85,255,255)]
		,[(90,43,46),(124,255,255)]];

#这个颜色时否在这个范围内
def isColorInRange(color,min,max):
	h,s,v=color[0],color[1],color[2];
	#比较颜色
	if h>=min[0] and h<=max[0] and s>=min[1] and s<=max[1] and v>=min[2] and v<=max[2]:
		return True;
	return False;

#得到这个点的颜色编号
def getPointColorNum(color):
	for k in range(len(threshold)):
		colorRange=threshold[k];
		for i in range(0,len(colorRange),2):
			if i>=len(colorRange):
				break;
			min=colorRange[i];
			max=colorRange[i+1];
			#判断颜色是否在这个范围
			if isColorInRange(color,min,max):
				return k;
	return -1;
#print(isColorInRange((95,60,187),threshold[1][2],threshold[1][3]));
sat_W = 60  # hsv-pixels with a saturation s > sat_W are considered not to be a white facelet-pixel
val_W = 200  # hsv-pixels with a value v < sat_W are considered not to be a white facelet-pixel
orange_L = 6  # lowest allowed hue for color orange
orange_H = 25  # highest allowed hue for color orange
yellow_H = 34  # highest allowed hue for color yellow
green_H = 80  # highest allowed hue for color green
blue_H = 160  # highest allowed hue for color blue
def getPointColorNum2(color):
	mh,ms,mv=color;
	if ms <= sat_W and mv >= val_W:
		return 1, 'white'
	elif orange_L <= mh and mh <orange_H:
		return 2, 'orange'
	elif orange_H <= mh and mh <yellow_H:
		return 3, 'yellow'
	elif yellow_H <= mh and mh <green_H:
		if ms < 150:
			return 1, 'white'  # green saturation is always higher
		else:
			return 4, 'green'
	elif green_H <= mh and mh < blue_H:
		if ms < 150:
			return 1, 'white'  # blue saturation is always higher
		else:
			return 5, 'blue'
	else:
		return 0, 'red';

#通过颜色统计的方法获取这个块的颜色编号
def getBlockColorNum(block):
	global count;
	count+=1;
	img=block.copy();
	#保存统计之后的每种颜色的点的数量
	res=[0,0,0,0,0,0];
	#图片归一化
	block=cv.resize(block,(8,8));
	#转hsv
	hsv=cv.cvtColor(block,cv.COLOR_BGR2HSV);
	useMean=False;
	if useMean==False:
		h,s,v=0,0,0;
		countV=0;
		#开始遍历计算
		for i in range(hsv.shape[0]):
			for j in range(hsv.shape[1]):
				#排除是黑色的点
				if isColorInRange(hsv[i][j],(0,0,0),(180,255,46)):
					continue;
				#判断这个点是哪一种颜色对应得编号
				num=getPointColorNum(hsv[i][j]);
				h+=hsv[i][j][0];
				s+=hsv[i][j][1];
				v+=hsv[i][j][2];
				countV+=1;
				if num!=-1:
					#对这种颜色的点的数量加一
					res[num]+=1;
		#找出数量最多的点的编号
		maxCount=0;
		index=-1;
		for i in range(6):
			if maxCount<res[i]:
				maxCount=res[i];
				index=i;
		#判断有没有识别错误的情况
		print(count,getColorWordByNum(index),h//countV,s//countV,v//countV);
		cv.imwrite("C:/Users/ASUS/Desktop/test/little/"+str(count)+".jpg",img);
		return index,getColorWordByNum(index);
	else:
		#使用均值
		index=getPointColorNum(cv.mean(hsv));
		print(count,getColorWordByNum(index));
		#cv.imwrite("C:/Users/ASUS/Desktop/test/little/"+str(count)+".jpg",img);
		return index,getColorWordByNum(index);
			
#获取这个编号代表的颜色中文
def getColorWordByNum(num):
	if num==0:
		return "red";
	elif num==1:
		return "white";
	elif num==2:
		return "orange";
	elif num==3:
		return "yellow";
	elif num==4:
		return "green";
	elif num==5:
		return "blue";
	elif num==-1:
		return "None";
'''	
for i in range(54):
	img=cv.imread("C:\\Users\\ASUS\\Desktop\\img\\little\\100"+str(i+1)+".jpg");
	num,key=getBlockColorNum2(img);
	#cv.putText(img, key, (10, 10), cv.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 255), 2);
	print(i+1,key);
	'''
#根据HSV颜色来识别
def hsvColorClassifie(blocks):
	#保存所有块的类别
	blocksType=[[1,1,1,1,1,1,1,1,1],
				[1,1,1,1,2,1,1,1,1],
				[1,1,1,1,3,1,1,1,1],
				[1,1,1,1,4,1,1,1,1],
				[1,1,1,1,5,1,1,1,1],
				[1,1,1,1,6,1,1,1,1]];
	#先识别6个中心块,用于后面的块来找自己是哪一个面的
	centerColorNum=[0,0,0,0,0,0];
	for k in range(6):
		num,key=getBlockColorNum(blocks[k][4]);
		centerColorNum[k]=num;
	#开始识别所有的小块
	for i in range(6):
		for j in range(9):
			#中心块不用再识别
			if(j==4):
			 	continue;
			num,key=getBlockColorNum(blocks[i][j]);
			#找出这个颜色对应的面的编号
			for k in range(6):
				if centerColorNum[k]==num:
					blocksType[i][j]=k+1;
					break;
	return blocksType;

#通过加权欧氏距离匹配分类
def rgbWeightDistance(blocks):
	global count;
	count=0;
	#保存所有块的类别(1,2,3,4,5,6)
	blocksType=[[1,1,1,1,1,1,1,1,1],
				[1,1,1,1,2,1,1,1,1],
				[1,1,1,1,3,1,1,1,1],
				[1,1,1,1,4,1,1,1,1],
				[1,1,1,1,5,1,1,1,1],
				[1,1,1,1,6,1,1,1,1]];
	#保存几个中间块的平均rgb色
	centerColor=[];
	for i in range(6):
		centerColor.append(getBlockBGRAvg(blocks[i][4]));
	# 开始遍历所有块，计算相似度
	for i in range(6):
		for j in range(9):
			#中心块不需要参与计算
			if(j==4):
			 	continue;
			# 得到这个块
			block=blocks[i][j];
			# 计算当前块的RGB均值
			curColor=getBlockBGRAvg(block);
			# 计算与6个中心块的欧氏距离相似度并得到最相近的
			maxSimilarity=100000000;
			type=1;
			for k in range(6):
				# 获取相似度
				similarity=getRGBWDIS(curColor,centerColor[k]);
				# 越小越相似
				if similarity<maxSimilarity:
					maxSimilarity=similarity;
					type=k+1;
			# 类型赋值
			#print(count,type)
			blocksType[i][j]=type;
	return blocksType;

#对所有小块分类
#为每一个小块都添加一个类别标注
def classifie(blocks,method=RGB_WEIGHT_DIS):
	if method==RGB_WEIGHT_DIS:
		return rgbWeightDistance(blocks);
	elif method==HSV_COLOR_RANGE:
		return hsvColorClassifie(blocks);
	
	